package com.yonyou.pmclouds.plan.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.billstatus.BillStatusConst;
import com.yonyou.pmclouds.basecom.bp.processor.AuditInfoUpdateProcessor;
import com.yonyou.pmclouds.basecom.bp.template.SingleDeleteBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleInsertBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleUpdateBpTemplate;
import com.yonyou.pmclouds.basecom.consts.BillTypeConst;
import com.yonyou.pmclouds.basecom.entity.SuperVO;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.exception.ConcurrentOperationException;
import com.yonyou.pmclouds.basecom.lock.AutoReleaseLockUtil;
import com.yonyou.pmclouds.plan.entity.PlanProgressVO;
import com.yonyou.pmclouds.plan.entity.ScheduleItemVO;
import com.yonyou.pmclouds.plan.entity.ScheduleReportVO;
import com.yonyou.pmclouds.plan.entity.ScheduleVO;
import com.yonyou.pmclouds.plan.mapper.ScheduleMapper;
import com.yonyou.pmclouds.plan.processor.*;
import com.yonyou.pmclouds.plan.rmiitf.*;
import com.yonyou.pmclouds.workflow.aspect.PMApprove;
import com.yonyou.pmclouds.workflow.service.rmiitf.IFlowApproveBuziService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Description: 进度计划编制服务类
 * @Author: zhangzhonghao
 * @Date: 2020-03-06
 */

@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = IScheduleService.class)
public class ScheduleServiceImpl implements IScheduleService, IFlowApproveBuziService {

    private static final String LOCK_PREFIX = "schedule_";

    @Autowired
    private ScheduleMapper scheduleMapper;

    @Autowired
    private ScheduleInsertBeforeProcessor insertBeforeProcessor;

    @Autowired
    private ScheduleInsertItemProcessor insertItemProcessor;

    @Autowired
    private ScheduleSetPlanDateProcessor setPlanDateProcessor;

    @Autowired
    private ScheduleUpdateBeforeProcessor updateBeforeProcessor;

    @Autowired
    private ScheduleUpdateItemProcessor updateItemProcessor;

    @Autowired
    private ScheduleDeleteAfterProcessor deleteAfterProcessor;

    @Autowired
    private ScheduleAdjustBeforeProcessor adjustBeforeProcessor;

    @Autowired
    private ScheduleAdjustItemProcessor adjustItemProcessor;

    @Autowired
    private IScheduleQueryService scheduleQueryService;

    @Autowired
    private IScheduleItemQueryService itemQueryService;

    @Autowired
    private IScheduleItemService itemService;

    /**
     * 计划编制新增
     *
     * @param scheduleVO 计划编制VO
     */
    @Override
    public ScheduleVO insert(ScheduleVO scheduleVO) throws BusinessException {
        if (!AutoReleaseLockUtil.addAutoReleaseLock(LOCK_PREFIX + scheduleVO.getPkProject())) {
            throw new ConcurrentOperationException();
        }

        if (StringUtils.isNotEmpty(scheduleVO.getPkSchedule())) {
            return update(scheduleVO);
        }

        SingleInsertBpTemplate<ScheduleVO> insertBpTemplate = new SingleInsertBpTemplate<>(scheduleMapper, false);

        // 校验必填项、设置默认值
        insertBpTemplate.addBeforeProcessor(insertBeforeProcessor);

        // 保存计划任务
        insertBpTemplate.addBeforeProcessor(insertItemProcessor);

        // 根据计划任务时间推算计划时间
        insertBpTemplate.addBeforeProcessor(setPlanDateProcessor);

        return insertBpTemplate.insert(scheduleVO);
    }

    /**
     * 计划编制删除
     *
     * @param scheduleVO 计划编制VO
     */
    @Override
    public ScheduleVO delete(ScheduleVO scheduleVO) throws BusinessException {
        SingleDeleteBpTemplate<ScheduleVO> deleteBpTemplate = new SingleDeleteBpTemplate<>(scheduleMapper);
        deleteBpTemplate.addAfterProcessor(deleteAfterProcessor);
        return deleteBpTemplate.delete(scheduleVO);
    }

    /**
     * 计划编制修改
     *
     * @param scheduleVO 计划编制VO
     */
    @Override
    public ScheduleVO update(ScheduleVO scheduleVO) throws BusinessException {
        SingleUpdateBpTemplate<ScheduleVO> updateBpTemplate = new SingleUpdateBpTemplate<>(scheduleMapper,
                new String[]{ScheduleVO.NAME, ScheduleVO.PLAN_START_DATE, ScheduleVO.PLAN_END_DATE, ScheduleVO.PLAN_DAYS,
                ScheduleVO.MODIFIER, ScheduleVO.MODIFY_TIME, ScheduleVO.CHANGE_FLAG});

        // 添加修改时间、修改人
        updateBpTemplate.addBeforeProcessor(new AuditInfoUpdateProcessor<ScheduleVO>());

        // 保存前校验
        updateBpTemplate.addBeforeProcessor(updateBeforeProcessor);

        // 修改任务项
        updateBpTemplate.addBeforeProcessor(updateItemProcessor);

        // 修改计划时间
        updateBpTemplate.addBeforeProcessor(setPlanDateProcessor);

        return updateBpTemplate.update(scheduleVO);
    }

    @Override
    public ScheduleReportVO updateProgress(ScheduleReportVO reportVO) throws BusinessException {
        if (reportVO == null) {
            return null;
        }

        itemService.updateProgress(reportVO);

        return reportVO;
    }

    /**
     * 计划审批提交
     *
     * @param scheduleVO 计划VO
     * @return 提交后计划VO
     */

    @Override
    @PMApprove(trigger = "commit")
    public ScheduleVO commit(ScheduleVO scheduleVO) throws BusinessException {
        return scheduleVO;
    }

    @Override
    public ScheduleVO updateScheduleForAdjust(ScheduleVO scheduleVO) throws BusinessException {
        String oldPkSchedule = scheduleVO.getPkSchedule();
        scheduleVO.setOldPkSchedule(oldPkSchedule);

        SingleInsertBpTemplate<ScheduleVO> insertBpTemplate = new SingleInsertBpTemplate<>(scheduleMapper);

        // 校验必填项、设置默认值
        insertBpTemplate.addBeforeProcessor(adjustBeforeProcessor);

        // 保存计划任务
        insertBpTemplate.addBeforeProcessor(adjustItemProcessor);

        // 根据计划任务时间推算计划时间
        insertBpTemplate.addBeforeProcessor(setPlanDateProcessor);

        ScheduleVO result = insertBpTemplate.insert(scheduleVO);

        // 修改旧版本
        ScheduleVO oldScheduleVO = scheduleQueryService.queryById(oldPkSchedule);
        if(oldScheduleVO == null){
            return result;
        }

        oldScheduleVO.setLastFlag("N");

        SingleUpdateBpTemplate<ScheduleVO> updateBpTemplate = new SingleUpdateBpTemplate<>(scheduleMapper,
                new String[]{ScheduleVO.LAST_FLAG, ScheduleVO.MODIFIER, ScheduleVO.MODIFY_TIME, ScheduleVO.CHANGE_FLAG});
        updateBpTemplate.addBeforeProcessor(new AuditInfoUpdateProcessor<ScheduleVO>());
        updateBpTemplate.update(oldScheduleVO);

        return result;
    }

    @Override
    @PMApprove
    public ScheduleVO addDefault(ScheduleVO scheduleVO) throws BusinessException {
        if(StringUtils.isEmpty(scheduleVO.getPkProject())){
            throw new BusinessException("项目主键不能为空");
        }
       //List<ScheduleVO> scheduleVOS = scheduleQueryService.queryByPkProject(scheduleVO.getPkProject());
        List<ScheduleVO> scheduleVOS = scheduleMapper.queryByPkProject(scheduleVO.getPkProject());
        if(scheduleVOS != null && scheduleVOS.size() > 0){
            for(ScheduleVO scheduleVOTemp : scheduleVOS){
                if(scheduleVOTemp.getName().equalsIgnoreCase(scheduleVO.getName()) && scheduleVOTemp.getCode().equalsIgnoreCase(scheduleVO.getCode())){
                    throw new BusinessException("已经添加默认计划，不允许重复添加！");
                }
            }
        }

        return this.insert(scheduleVO);
    }

    @Override
    public SuperVO approveByPkBill(String pk_bill, byte billStatus) throws BusinessException {
        ScheduleVO scheduleVO = scheduleQueryService.queryById(pk_bill);
        SingleUpdateBpTemplate<ScheduleVO> updateBpTemplate = new SingleUpdateBpTemplate<>(scheduleMapper,
                new String[]{ScheduleVO.BILL_STATUS});
        scheduleVO.setBillstatus(billStatus);
        return updateBpTemplate.update(scheduleVO);
    }

    @Override
    public SuperVO rejectByPkBill(String pk_bill) throws BusinessException {
        ScheduleVO scheduleVO = scheduleQueryService.queryById(pk_bill);
        SingleUpdateBpTemplate<ScheduleVO> updateBpTemplate = new SingleUpdateBpTemplate<>(scheduleMapper,
                new String[]{ScheduleVO.BILL_STATUS});
        scheduleVO.setBillstatus(BillStatusConst.COMMON_REJECT_STATUS);
        return updateBpTemplate.update(scheduleVO);
    }

    @Override
    public SuperVO queryDetailForWorkFlow(String pk_bill) throws BusinessException {
        return scheduleQueryService.queryById(pk_bill);
    }

    @Override
    public String getBillType() {
        return BillTypeConst.PROCESS_PLAN_BILLTYPE;
    }

    @Override
    public SuperVO deleteBill(SuperVO businessVO) throws BusinessException {
        return this.delete((ScheduleVO) businessVO);
    }

    @Override
    public Object getMapper() {
        return scheduleMapper;
    }
}
